﻿#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
using std::cout;
using std::cin;
using std::endl;
using std::sort;

//class Time
//{
//public:
//	Time(int hour=5)//这个作为全缺省构造函数可以作为默认构造函数因为可以不用传参，因此这样就可以不用写到初始化列表中。//如果没有这个=5那下面的,t(5)要有
//		:_hour(hour)
//	{
//		cout << "Time()" << endl;
//	}
//private:
//	int _hour;
//};
//
//class Date
//{
//public:
//	Date(int&x,int year, int month=2, int day=10)//1.引⽤成员变量，2.const成员变量，3.没有默认构造的类类型变量，必须放在初始化列表位置进⾏初始化，否则会编译报错。例如ref和i
//		:i(1)//未显示在初始化列表的变量会去声明找缺省值，如果没有，如果是内置类型初始化为随机值，如果是类类型就去调用类的默认构造函数
//		//,_year(year)
//		//,_month(month)//如果注释掉，且声明处没有给缺省值编译器也会走，但是行为不知道，有可能是随机值，也可能是0
//		,_day(day)//初始化列表的使⽤⽅式是以⼀个冒号开始，接着是⼀个以逗号分隔的数据成员列表，每个"成员变量"后⾯跟⼀个放在括号中的初始值 或表达式。
//		//,_year(month)//每个成员变量在初始化列表中只能出现⼀次
//		//,ref(month)//这样会导致野引用，因为month出了作用域就会被销毁
//		,ref(x)
//		//每个成员变量都要走初始化列表
//		//初始化列表是按成员变量声明来走
//		//,_t(5)//如果这个类类型没有默认构造函数。不初始化就会报错 说没有默认构造函数  属于上面说的第三点 //也可以不弄默认构造，在声明处搞个缺省值
//	{
//		_year = year;
//	}
//private:
//	//声明
//	int _year=2000;//缺省值
//	int _month;
//	int _day=18;
//
//	int& ref;//这个引用和const int 必须在声明变量的时候初始化
//	const int i;
//	//Time _t=10;
//	Time _t;
//};
//
//int main()
//{
//	int xx = 0;
//	//int& x = xx;
//	//const int c = 5;
//	//int& a;//报错
//	//const int b;//报错
//
//	Date d1(xx,2025, 5, 3);
//	xx++;
//
//	return 0;
//}

//------------------------------------------------------------------------------
//typedef int STDataType;
//class Stack
//{
//public:
//	//Stack(int n = 4)
//	//{
//	//	_a = (STDataType*)malloc(sizeof(STDataType) * n);
//	//	if (nullptr == _a)
//	//	{
//	//		perror("malloc申请空间失败");
//	//		return;
//	//	}
//	//	_capacity = n;
//	//	_top = 0;
//	//}
//
//	Stack(int n = 4)//构造函数
//		:_a((STDataType*)malloc(sizeof(STDataType)* n))
//		//,_top(0)
//		,_capacity(n)
//	{	
//		if (_a == nullptr)
//		{
//			perror("malloc");
//			exit(1);
//		}
//	}
//
//	// st2(st1)
//	Stack(const Stack& s)//拷贝构造函数
//	{
//		cout << "Stack(Stack& s)" << endl;
//		_a = (STDataType*)malloc(sizeof(STDataType) * s._capacity);
//		if (nullptr == _a)
//		{
//			perror("malloc申请空间失败");
//			return;
//		}
//
//		memcpy(_a, s._a, sizeof(STDataType) * s._top);
//		_top = s._top;
//		_capacity = s._capacity;
//	}
//
//	void Push(const STDataType& x)
//	{
//		// 扩容
//		_a[_top] = x;
//		_top++;
//	}
//
//	int Top()
//	{
//		return _a[_top-1];
//	}
//
//	~Stack()//析构函数
//	{
//		cout << "~Stack()" << endl;
//		free(_a);
//		_a = nullptr;
//		_top = _capacity = 0;
//	}
//private:
//	STDataType* _a;
//	size_t _capacity;
//	size_t _top=0;
//};
//
//class MyQueue
//{
//public:
//	/*MyQueue(int n = 4)
//		:_pushst(n)
//		,_popst(n)
//		,_size(0)
//	{}*/
//
//	MyQueue(int n = 4)
//		:_pushst(n)
//		,_popst(n)
//	{}
//
//private:
//	// 缺省值
//	Stack _pushst;
//	Stack _popst;
//	int _size = 0;
//};
//
//// 单链表
//struct SListNode
//{
//	SListNode* _next;
//	int _val;
//};
//
//class SList
//{
//public:
//private:
//	SListNode* _head = nullptr;
//};
//
//// 双向循环链表
//struct DListNode
//{
//	DListNode* _next;
//	DListNode* _prev;
//
//	int _val;
//};
//
//class DList
//{
//public:
//	DList()
//		:_head((DListNode*)malloc(sizeof(DListNode)))
//	{
//		if (_head == nullptr)
//		{
//			//...
//		}
//
//		_head->_prev = _head;
//		_head->_next = _head;
//	}
//
//private:
//	DListNode* _head;
//};
//
//class A
//{
//public:
//	/*A(int a)
//		:_a1(_a2)
//	{}*/
//
//	A(int a)
//		:_a1(a)
//	{}
//
//	/*A(int a)
//		:_a1(a)
//		, _a2(_a1)
//	{}*/
//
//	void Print() {
//	cout << _a1 << " " << _a2 << endl;
//	}
//private:
//	int _a2 = 2;
//	int _a1 = 2;
//};
//
//int main()
//{
//	//MyQueue q1;
//	//MyQueue q2(10);
//
//	//SList lt1;
//	//DList lt2;
//
//	A aa(5);
//	aa.Print();
//
//	return 0;
//}

//#include <iostream>
//using namespace std;
//
//class Time {
//public:
//    Time(int h)
//        : _h(h) 
//    { 
//        cout << "Time 构造，h=" << _h << endl; 
//    }
//private:
//    int _h;
//};
//
//class Event {
//public:
//    Event(int& r)
//        : _year(2025)
//        , _month(5)
//        , _day(4)
//        //, _t(12)         // Time 对象，必须初始化
//        , _ref(r)        // 引用
//        , _flag(true)    // const bool
//    {
//        // 构造体内不能再初始化上述成员，否则编译报错
//    }
//    void print() const {
//        cout << _year << "-" << _month << "-" << _day << endl;
//    }
//private:
//    int         _year;
//    int         _month;
//    int         _day;
//    Time        _t=10;      // 无默认构造，必须列表初始化
//    int& _ref;    // 引用，必须列表初始化
//    const bool  _flag;   // const，必须列表初始化
//};
//
//int main() {
//    int x = 100;
//    Event ev(x);
//    ev.print();  // 输出 2025-5-4
//    return 0;
//}

//------------------------------------------------------------------------------
//类型转换
//C语言的类型转换
// 1.整型之间
// 2、整型和浮点数之间
// 3、整型和指针之间
// 4、指针和指针之间
//	
//C++
// 内置类型 -> 类类型
// 类类型 -> 类类型
//

//class A
//{
//public:
//	// 构造函数explicit就不再支持隐式类型转换
//	//explicit A(int a1)
//	A(int a1)
//		:_a1(a1)
//	{
//		cout << "A(int a1)" << endl;
//	}
//
//	////explicit A(int a1, int a2)
//	A(int a1, int a2)
//		:_a1(a1)
//		, _a2(a2)
//	{}
//
//	A(const A& aa)//拷贝构造  临时对象拷贝构造到对象，  优化后编译器不走这个
//		:_a1(aa._a1)
//		,_a2(aa._a2)
//	{
//		cout << "A(const A& aa)" << endl;
//	}
//
//	void Print()const
//	{
//		cout << _a1 << " " << _a2 << endl;
//	}
//
//	int Get() const
//	{
//		return _a1 + _a2;
//	}
//private:
//	int _a1 = 1;
//	int _a2 = 2;
//};
//
//class B
//{
//public:
//	B(const A& a)
//		:_b(a.Get())
//	{}
//	void Print()const
//	{
//		cout << _b << endl;
//	}
//private:
//	int _b = 0;
//};
//
//class Stack
//{
//public:
//	void Push(const A& aa)
//	{}
//};
//
//int main()
//{
//	// 1构造一个A的临时对象，再用这个临时对象拷贝构造aa1
//	// 编译器遇到连续构造+拷贝构造->优化为直接构造
//	A aa1 = 5;//构造出临时对象，再拷贝构造给aa1
//
//	//A aa1(5);//这个是直接构造，初始化对象，不存在类型转化，没有拷贝构造的过程
//	
//	//A aa1;
//	aa1.Print();
//	const A& r1 = 3;//没有拷贝构造的过程，又因为临时对象具有常性，所以用const
//	r1.Print();
//
//	//A aa3 = { 3, 3 };
//	A aa3(3, 3);
//	aa3.Print();
//	const A& r2 = { 5,5 };
//
//	Stack st;
//	A aa2(2); // 有名对象
//	st.Push(aa2);
//
//	st.Push(2);		// 类型转换
//	st.Push({3,4}); // 类型转换
//
//
//	B b1 = aa1;// 类与类之间的类型转换
//	const B& r3 = aa1;// 类型转换
//	b1.Print();
//	r3.Print();
//
//	return 0;
//}

//------------------------------------------------------------------------------
// 实现一个类，计算程序中创建出了多少个类对象？

//#include<iostream>
//using namespace std;
//class A
//{
//public:
//	A(int x=0)
//	{
//		++_scount;
//	}
//	A(const A& t)//非静态的成员函数，可以访问任意的静态成员变量和静态成员函数。
//	{
//		++_scount;
//	}
//	~A()
//	{
//		--_scount;
//	}
//
//	//int GetACount()
//	static int GetACount()	//没有this指针
//	{
//		//_a1++; //不能访问非静态成员变量
//		return _scount;
//	}
//private:
//	//静态成员变量不属于某一个对象，而是属于整一个类，所有对象
//	// 类⾥⾯声明
//	static int _scount;//不能在这里给缺省值，因为缺省是用来走构造初始化列表的，而这个不属于某一个对象
//	int _a1 =1;
//	int _a2;
//};
//
////定义初始化
//int A::_scount = 0;
//
//int main()
//{
//	A aa1;
//	A aa2(aa1);
//	A aa3 = 5;
//	A aa[10];
//
//	//A::_scount++;
//	//A::_scount = 5;
//	//cout << A::_scount << endl;//如果是public就可以走,但是都可以修改//A::_scount = 5;
//	//cout << aa1._scount << endl;
//
//	cout<<A::GetACount()<<endl;//只有当静态函数才可以这样调用//“A::GetACount”: 调用非静态成员函数需要一个对象
//	cout<<aa1.GetACount()<<endl;
//
//	/*操作静态成员时，优先使用静态成员函数。
//	这符合面向对象设计的封装性、语义明确性，并避免不必要的对象依赖。*/
//	return 0;
//}

//------------------------------------------------------------------------------
//友元  友元分为：友元函数和友元类，在函数声明或者类声明的前⾯加friend，并且把友元声明放到⼀个类的⾥⾯。

//// 前置声明，都则A的友元函数声明编译器不认识B
//class B;
//class A
//{
//	// 友元函数声明
//	friend void func(const A& aa, const B& bb);
//private:
//	int _a1 = 1;
//	int _a2 = 2;
//};
//
//class B
//{
//	// 友元函数声明
//	friend void func(const A& aa, const B& bb);
//private:
//	int _b1 = 3;
//	int _b2 = 4;
//};
//
//void func(const A& aa, const B& bb)//外部友元函数可访问类的私有和保护成员，友元函数仅仅是⼀种声明，他不是类的成员函数。
//{
//	cout << aa._a1 << endl;
//	cout << aa._a2 << endl;
//	cout << bb._b1 << endl;
//	cout << bb._b2 << endl;
//}
//
//int main()
//{
//	A aa;
//	B bb;
//	func(aa, bb);
//	return 0;
//}

//class A
//{
//	// 友元类声明//B可以访问A类中的私有和保护成员，还有成员函数
//	friend class B;
//	//friend void func1(const A& aa);//这种友元函数要在类的外部，不能在其他类里面，不然也找不到私有和保护成员
//	//friend void func2(const A& aa);
//private:
//	int _a1 = 1;
//	int _a2 = 2;
//};
//
//class B
//{
//public:
//	void func1(const A& aa)//友元类中的成员函数都可以是另⼀个类的友元函数（可以访问另⼀个类中的私有和保护成员）
//	{
//		cout << aa._a1 << endl;
//		cout << _b1 << endl;
//	}
//
//	void func2(const A& aa)
//	{
//		cout << aa._a2 << endl;
//		cout << _b2 << endl;
//	}
//private:
//	int _b1 = 3;
//	int _b2 = 4;
//};
//
//int main()
//{
//	A aa;
//	B bb;
//	bb.func1(aa);
//	bb.func2(aa);
//	return 0;
//}

//------------------------------------------------------------------------------
//内部类
//• 如果⼀个类定义在另⼀个类的内部，这个内部类就叫做内部类。
// 内部类是⼀个独⽴的类，跟定义在全局相比，他只是受外部类类域限制和访问限定符限制，所以外部类定义的对象中不包含内部类。

//class A
//{
//private:
//	static int _k;
//	int _h = 1;
//
//public:
//	class B // B默认就是A的友元
//	{
//	public:
//		void foo(const A& a)
//		{
//			cout << _k << endl; //OK
//			cout << a._h << endl; //OK 内部类默认是外部类的友元类。
//			cout << _num << endl; //OK
//		}
//
//	private:
//		int _b1 = 1;
//		int _b2 = 1;
//		static int _num;
//	};
//};
//
//int A::_k = 1;
//int A::B::_num = 0;
//
//int main()
//{
//	cout << sizeof(A) << endl;
//	A aa1;
//	A::B bb1;
//	bb1.foo(aa1);
//	return 0;
//}

//------------------------------------------------------------------------------
//匿名对象  • ⽤ 类型(实参) 定义出来的对象叫做匿名对象，相⽐之前我们定义的 类型 对象名(实参) 定义出来的叫有名对象
//匿名对象⽣命周期只在当前⼀⾏，⼀般临时定义⼀个对象当前⽤⼀下即可，就可以定义匿名对象。
//class A
//{
//public:
//	A(int a = 0)
//		:_a(a)
//	{
//		cout << "A(int a)" << endl;
//		cout << _a << endl;
//	}
//	~A()
//	{
//		cout << "~A()" << endl;
//	}
//private:
//	int _a;
//};
//
//class Solution {
//public:
//	int Sum_Solution(int n) {
//		//...
//		return n;
//	}
//};
//
//int main()
//{
//	//有名对象
//	A aa1;
//	A aa2(12);
//	// 不能这么定义对象，因为编译器⽆法识别下⾯是⼀个函数声明，还是对象定义
//	//A aa1();
//
//
//	//匿名对象
//	A();
//	A(11);//生命周期只有一行，用完就销毁
//	//使用场景为，实例出对象只是为了函数调用，后续没有什么用处的时候，就可以用匿名对象，因为这样的代码只有一行
//
//	Solution s;
//	cout << s.Sum_Solution(5) << endl;
//
//	cout << Solution().Sum_Solution(5) << endl;//匿名对象的使用场景
//
//	// <
//	int values[] = { 40, 10, 100, 90, 20, 25 };
//	sort(values, values + 6);//左闭右开  //默认升序
//
//	// >
//	std::greater<int> gt;
//	sort(values, values + 6, gt);//降序
//	sort(values, values + 6, std::greater<int>());//匿名对象
//
//
//	return 0;
//}

//------------------------------------------------------------------------------
//编译器优化
class A
{
public:
	A(int a = 0)
		:_a1(a)
	{
		cout << "A(int a)" << endl;
	}
	A(const A& aa)
		:_a1(aa._a1)
	{
		cout << "A(const A& aa)" << endl;
	}
	A& operator=(const A& aa)
	{
		cout << "A& operator=(const A& aa)" << endl;
		if (this != &aa)
		{
			_a1 = aa._a1;
		}
		return *this;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
private:
	int _a1 = 1;
};

void f1(A aa)
{}

//int main()
//{
//	//构造+拷贝构造->优化直接构造
//	//A aa1 = 1;//构造出临时对象，然后拷贝构造给aa1
//
//	//// 传值传参 -> 无优化
//	//A aa1(1);
//	//f1(aa1);//拷贝构造给aa
//	//cout << endl << endl;
//
//	//// 构造+拷贝构造 -> 优化直接构造
//	//f1(A());//匿名对象
//	//cout << endl << endl;
//
//	// 构造+拷贝构造 -> 优化直接构造
//	//f1(1);//隐式类型转化  //A aa1 = 1 构造出临时对象，再拷贝构造给aa1
//	return 0;
//}

//A f2()
//{
//	A aa;
//	cout << &aa << endl;
//	return aa;
//}
//int main()
//{
//	// 传值返回
//	// 返回时一个表达式中，连续 拷贝构造+拷贝构造->优化一个拷贝构造 （vs2019 debug）
//	// 一些编译器会优化得更厉害，进行跨行合并优化，直接变为构造。（vs2022 debug）//分析语义场景，f2()没有接收返回值，觉得拷贝也是白拷贝，干脆就不拷贝了
//	//f2();
//	//cout << endl;
//
//	//A aa2 = f2();//按理是构造加返回时拷贝构造给临时对象，临时对象再拷贝构造给aa2
//	//cout << &aa2 << endl;//2022优化过//本质只创建了aa2,底层aa是aa2的引用，这样就不用拷贝了
//	//cout << endl;
//
//	// 一个表达式中，连续拷贝构造+赋值重载->无法优化
//	//A aa3;
//	//aa3 = f2();
//	//cout << endl;
//
//	return 0;
//}

int main()
{
	char arr[] = "abcd";  //arr栈区
	const char* ptr = "abcd";//ptr栈区，*ptr常量区
	const int x = 10;//x是常变量，故在栈区
	cout << (void*)arr << endl;
	cout << (void*)ptr << endl;
	printf("%p\n", &(*ptr) );
	printf("%p\n", &ptr);

}